﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace _11.TreeMultiSet
{
    class TreeMultiSet<T> : IEnumerable<T>
    {
        SortedDictionary<T, int> sortedDictionary;
        int count;

        public TreeMultiSet()
        {
            this.sortedDictionary = new SortedDictionary<T, int>();
            this.count = 0;
        }
        public TreeMultiSet(IComparer<T> comparer)
        {
            this.sortedDictionary = new SortedDictionary<T, int>(comparer);
            this.count = 0;
        }

        #region Properties

        public int Count
        {
            get
            {
                return count;
            }
        }
        #endregion

        #region Methods

        public void Add(T element)
        {
            if (sortedDictionary.ContainsKey(element))
            {
                sortedDictionary[element]++;
            }
            else
            {
                sortedDictionary.Add(element, 1);
            }
            count++;
        }

        public int Find(T element)
        {
            if (sortedDictionary.ContainsKey(element))
            {
                return sortedDictionary[element];
            }
            else
            {
                return 0;
            }
        }

        public void Delete(T element)
        {
            if (sortedDictionary.ContainsKey(element))
            {
                if (sortedDictionary[element] > 1)
                {
                    sortedDictionary[element]--;
                }
                else
                {
                    sortedDictionary.Remove(element);
                }
                count--;
            }
            else
            {
                //throw new ArgumentException("There is no such element in TreeMultiSet");
            }
        }

        public void DeleteAll(T element)
        {
            if (sortedDictionary.ContainsKey(element))
            {
                count -= sortedDictionary[element];
                sortedDictionary.Remove(element);
            }
            else
            {
                throw new ArgumentException("There is no such element in TreeMultiSet");
            }
        }

        public T FindMin()
        {
            return sortedDictionary.First().Key;
        }

        public T FindMax()
        {
            return sortedDictionary.Last().Key;
        }

        public void DeleteFirst()
        {
            KeyValuePair<T, int> minElements = sortedDictionary.First();
            if (minElements.Value > 1)
            {
                sortedDictionary[minElements.Key]--;
            }
            else
            {
                sortedDictionary.Remove(minElements.Key);
            }
            count--;
        }

        public void DeleteLast()
        {
            KeyValuePair<T, int> maxElements = sortedDictionary.Last();
            if (maxElements.Value > 1)
            {
                sortedDictionary[maxElements.Key]--;
            }
            else
            {
                sortedDictionary.Remove(maxElements.Key);
            }
            count--;
        }

        #endregion

        #region IEnumerable

        public IEnumerator<T> GetEnumerator()
        {
            foreach (KeyValuePair<T, int> pair in sortedDictionary)
            {
                for (int i = 0; i < pair.Value; i++)
                {
                    yield return pair.Key;
                }
            }
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return ((IEnumerable<T>)this).GetEnumerator();
        }

        #endregion
    }
}
